package com.lanchetech.merchant.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.request.FreezeAmountReq;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.FreezeAmountVO;
import com.lanchetech.bean.vo.TenantFundVO;
import com.lanchetech.common.enums.ResultCode;
import com.lanchetech.common.enums.TenantWithdrawStatusEnum;
import com.lanchetech.common.enums.TradeTypeEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.merchant.service.FundService;
import com.lanchetech.service.DaoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class FundServiceImpl implements FundService {

    @Autowired
    TenantWithdrawMapper tenantWithdrawMapper;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    BalanceFlowMapper balanceFlowMapper;

    @Autowired
    TenantFlowMapper tenantFlowMapper;

    @Autowired
    FreezeAmountMapper freezeAmountMapper;

    @Autowired
    DaoService daoService;

    @Override
    public ResultData<BasePageResp<TenantWithdraw>> getTenantWithdrawPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<TenantWithdraw> list = tenantWithdrawMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp createTenantWithdraw(TenantWithdraw req) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();


        // 判断余额是否足够
        Tenant tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());

        BigDecimal sum = tenantWithdrawMapper.sumByStatus(TenantWithdrawStatusEnum.PROCESSING.getStatus());

        if (sum == null) {
            sum = BigDecimal.ZERO;
        }

        //冻结金额
        BigDecimal freeze = freezeAmountMapper.sumAmount();
        if (tenant.getPoint().subtract(sum).compareTo(req.getAmount()) > -1 && tenant.getPoint().subtract(freeze).subtract(sum).compareTo(req.getAmount()) < 0) {
            return new BaseResp(ResultCode.FREEZE_POINT);
        }

        // 余额减去提现中的，要大于当前要提现的
        if (tenant.getPoint().subtract(sum).compareTo(req.getAmount()) > -1) {
            tenantWithdrawMapper.insert2(TenantWithdraw.builder()
                    .amount(req.getAmount())
                    .status(TenantWithdrawStatusEnum.PROCESSING.getStatus())
                    .createdAt(new Date())
                    .updatedAt(new Date())
                    .build());
        } else {
            return new BaseResp(ResultCode.INSUFFICIENT_BALANCE);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<TenantFundVO> getTenantFundInfo() {
        TenantFundVO vo = new TenantFundVO();
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Tenant tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());
        BigDecimal freezeAmout = freezeAmountMapper.sumAmount() == null ? BigDecimal.ZERO : freezeAmountMapper.sumAmount();
        vo.setPoint(tenant.getPoint().subtract(freezeAmout));
        vo.setCoin(tenant.getCoin());
        vo.setWithdrawProcessing(tenantWithdrawMapper.sumByStatus(TenantWithdrawStatusEnum.PROCESSING.getStatus()));
        vo.setWithdrawSuccess(tenantWithdrawMapper.sumByStatus(TenantWithdrawStatusEnum.SUCCESS.getStatus()));
        vo.setTotalFreezeAmount(freezeAmout);
        return new ResultData<>(vo);
    }

    @Override
    public BaseResp topUpCoin(BigDecimal coin) {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Tenant tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());
        if (tenant.getPoint().multiply(new BigDecimal(100)).compareTo(coin) >= 0) {
            // 先扣除余额
            BigDecimal amount = coin.divide(new BigDecimal(100));
            BigDecimal point = tenant.getPoint().subtract(amount);
            tenantMapper.updatePointById(point, tenant.getId());
            // TODO 创建余额流水明细
//            balanceFlowMapper.insert2(BalanceFlow.builder()
//                    .amount(amount)
//                    .tradeType(TradeTypeEnum.BUY_COIN.getTradeType())
//                    .type(TradeTypeEnum.BUY_COIN.getType())
//                    .point(point)
//                    .createdAt(new Date())
//                    .remark("购买"+coin.toString()+"个积分")
//                    .build());
            // 增加积分
            tenantMapper.updateCoinById(tenant.getCoin().add(coin), tenant.getId());
        } else {
            return new BaseResp(ResultCode.INSUFFICIENT_BALANCE);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<TenantFlow>> getBalanceFlowPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<TenantFlow> list = tenantFlowMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<FreezeAmountVO>> getFreezeAmountPage(FreezeAmountReq req) {
        req.setTenantId(null);
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<FreezeAmountVO> list = freezeAmountMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, Orders> ordersMap = daoService.getOrdersMap(list.stream().map(FreezeAmountVO::getOrderId).collect(Collectors.toList()));
            Map<Long, User> userMap = daoService.getUserMap(ordersMap.values().stream().map(Orders::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                Orders orders = ordersMap.get(item.getOrderId());
                if (null != orders) {
                    item.setOrderRemark(orders.getRemark());
                    item.setUserNickname(userMap.get(orders.getUserId()).getNickname());
                    item.setUserAvatar(userMap.get(orders.getUserId()).getAvatar());
                }
            });
        }
        ResultData<BasePageResp<FreezeAmountVO>> result = PageHelpUtil.buildPage(list, page);
        result.getValue().setExtra(freezeAmountMapper.sumAmountStatistics(req));
        return result;
    }
}